#!/bin/bash -ex

# get the values of $SNAP_DATA and $SNAP using the current symlink instead of
# the default behavior which has the revision hard-coded, which breaks after
# a refresh
SNAP_DATA_CURRENT=${SNAP_DATA/%$SNAP_REVISION/current}
SNAP_CURRENT=${SNAP/%$SNAP_REVISION/current}

# install all the config files from $SNAP/config/SERVICE/res/configuration.toml 
# into $SNAP_DATA/config
# note that app-service-configurable is handled separately
mkdir -p "$SNAP_DATA/config"
for service in security-file-token-provider security-proxy-setup security-secretstore-setup core-command core-data core-metadata support-notifications support-scheduler sys-mgmt-agent device-virtual security-bootstrapper; do
    if [ ! -f "$SNAP_DATA/config/$service/res/configuration.toml" ]; then
        mkdir -p "$SNAP_DATA/config/$service/res"

        # for security-bootstrapper, we have two different configuration toml, one for bootstrap-redis and one for security-bootstrapper itself
        # the bootstrap-redis run the configureRedis subcommand portion and associated
        # configuration.toml file
        # the bootstrap-consul or consul-bootstrapper runs the setupRegistryACL subcommand portion and associated configuration.toml file
        if [ "$service" == "security-bootstrapper" ]; then
            mkdir -p "$SNAP_DATA/config/$service/res-bootstrap-redis"
            cp "$SNAP/config/$service/res-bootstrap-redis/configuration.toml" \
                "$SNAP_DATA/config/$service/res-bootstrap-redis/configuration.toml"
        fi
        cp "$SNAP/config/$service/res/configuration.toml" "$SNAP_DATA/config/$service/res/configuration.toml"

        # replace $SNAP, $SNAP_DATA, $SNAP_COMMON env vars for file-token-provider,
        # as it doesn't support env var overrides
        if [ "$service" == "security-file-token-provider" ]; then
            sed -i -e "s@\$SNAP_COMMON@$SNAP_COMMON@g" \
                -e "s@\$SNAP_DATA@$SNAP_DATA_CURRENT@g" \
                -e "s@\$SNAP@$SNAP_CURRENT@g" \
                "$SNAP_DATA/config/$service/res/configuration.toml"
        fi
    fi
done

# install the template config yaml file for securing Kong's admin APIs in security-secretstore-setup service
if [ ! -f "$SNAP_DATA/config/security-secretstore-setup/res/kong-admin-config.template.yml" ]; then
    cp "$SNAP/config/security-secretstore-setup/res/kong-admin-config.template.yml" \
        "$SNAP_DATA/config/security-secretstore-setup/res/kong-admin-config.template.yml"
fi

# handle app-service-configurable's rules-engine profile
# 1. create the directory
# 2. copy the config files from $SNAP into $SNAP_DATA
mkdir -p "$SNAP_DATA/config/app-service-configurable/res/rules-engine"
if [ ! -f "$SNAP_DATA/$RULES_ENGINE_PROFILE_CONFIG" ]; then
    cp "$SNAP/config/res/rules-engine/configuration.toml" \
       "$SNAP_DATA/config/app-service-configurable/res/rules-engine/configuration.toml"
fi

# handle device-virtual devices and device profiles
mkdir -p "$SNAP_DATA/config/device-virtual/res/devices"
cp "$SNAP/config/device-virtual/res/devices/devices.toml" \
   "$SNAP_DATA/config/device-virtual/res/devices/devices.toml"

mkdir -p "$SNAP_DATA/config/device-virtual/res/profiles"
for profileType in bool float int uint binary; do
    cp "$SNAP/config/device-virtual/res/profiles/device.virtual.$profileType.yaml" \
       "$SNAP_DATA/config/device-virtual/res/profiles/device.virtual.$profileType.yaml"
done

# create kuiper directories in $SNAP_DATA
if [ ! -f "$SNAP_DATA/kuiper/data" ]; then
    mkdir -p "$SNAP_DATA/kuiper/data"
    mkdir -p "$SNAP_DATA/kuiper/etc/sources"

    cp "$SNAP/etc/"*.yaml "$SNAP_DATA/kuiper/etc"
    cp "$SNAP/etc/sources/"*.yaml "$SNAP_DATA/kuiper/etc/sources"
fi

# copy the security-file-token-provider config into place
cp "$SNAP/config/security-file-token-provider/res/token-config.json" "$SNAP_DATA/config/security-file-token-provider/res/token-config.json"

# ensure consul dirs exist
mkdir -p "$SNAP_DATA/consul/data"
mkdir -p "$SNAP_DATA/consul/config"

# ensure secrets dir exists
mkdir -p "$SNAP_DATA/secrets"

# touch all the kong log files to ensure they exist
mkdir -p "$SNAP_COMMON/logs"
for type in proxy admin; do
    for op in access error; do
        touch "$SNAP_COMMON/logs/kong-$type-$op.log"
    done
done

# create redis data dir
mkdir -p "$SNAP_DATA/redis"
# create redis conf dir
mkdir -p "$SNAP_DATA/redis/conf"

# set redis as the prevdbtype in order to support configure hook switching
echo "redis" > "$SNAP_DATA/prevdbtype"

# the vault config needs to be generated with sed, replacing $SNAP_DATA in the file 
# with the actual absolute directory
# note that if anyone ever somehow has a "@" in their $SNAP_DATA this will likely break :-/
if [ ! -f "$SNAP_DATA/config/security-secret-store/vault-config.hcl" ]; then
    mkdir -p "$SNAP_DATA/config/security-secret-store"
    sed "s@\$SNAP_DATA@$SNAP_DATA_CURRENT@g" "$SNAP/config/security-secret-store/vault-config.hcl.in" > "$SNAP_DATA/config/security-secret-store/vault-config.hcl"
    chmod 644 "$SNAP_DATA/config/security-secret-store/vault-config.hcl"
fi

# the kong config file needs to be generated with 3 changes from the default one included in the snap
# - we set the prefix to be $SNAP_DATA/kong as an absolute path (note that this has to be done here in the install hook)
# - we set the nginx user to be root
if [ ! -f "$SNAP_DATA/config/security-proxy-setup/kong.conf" ]; then
    mkdir -p "$SNAP_DATA/config/security-proxy-setup"
    cp "$SNAP/config/security-proxy-setup/kong.conf" "$SNAP_DATA/config/security-proxy-setup/kong.conf"
    # replace the default prefix setting with an absolute path using $SNAP_DATA
    # note that if anyone ever has a "@" in their $SNAP_DATA this will likely fail
    sed -i "s@#prefix = /usr/local/kong/@prefix = $SNAP_DATA_CURRENT/kong@" "$SNAP_DATA/config/security-proxy-setup/kong.conf"

    # also replace the default nginx user/group to be root
    sed -i "s@#nginx_user = nobody nobody@nginx_user = root root@" "$SNAP_DATA/config/security-proxy-setup/kong.conf"
fi

# setup postgres db config file with env vars replaced
if [ ! -f "$SNAP_DATA/etc/postgresql/10/main/postgresql.conf" ]; then
    mkdir -p "$SNAP_DATA/etc/postgresql/10/main"
    cp "$SNAP/etc/postgresql/10/main/postgresql.conf" "$SNAP_DATA/etc/postgresql/10/main/postgresql.conf"
    # do replacement of the $SNAP, $SNAP_DATA, $SNAP_COMMON environment variables in the config files
    sed -i -e "s@\$SNAP_COMMON@$SNAP_COMMON@g" \
        -e "s@\$SNAP_DATA@$SNAP_DATA_CURRENT@g" \
        -e "s@\$SNAP@$SNAP_CURRENT@g" \
        "$SNAP_DATA/etc/postgresql/10/main/postgresql.conf"
fi

# ensure the postgres data directory exists and is owned by snap_daemon
mkdir -p "$SNAP_DATA/postgresql" 
chown -R snap_daemon:snap_daemon "$SNAP_DATA/postgresql" 

# setup the postgres data directory
"$SNAP/bin/drop-snap-daemon.sh" "$SNAP/usr/lib/postgresql/10/bin/initdb" -D "$SNAP_DATA/postgresql/10/main"

# ensure the sockets dir exists and is properly owned
mkdir -p "$SNAP_COMMON/sockets"
chown -R snap_daemon:snap_daemon "$SNAP_COMMON/sockets" 

# start postgres up and wait a bit for it so we can create the database and user
# for kong
snapctl start "$SNAP_NAME.postgres"

# add a kong user and database in postgres - note we have to run these through
# the perl5lib-launch scripts to setup env vars properly and we need to loop
# trying to do this because we have to wait for postgres to start up
iter_num=0
MAX_POSTGRES_INIT_ITERATIONS=10
until "$SNAP/bin/drop-snap-daemon.sh" "$SNAP/bin/perl5lib-launch.sh" "$SNAP/usr/bin/createdb" kong; do
    sleep 1
    iter_num=$(( iter_num + 1 ))
    if [ $iter_num -gt $MAX_POSTGRES_INIT_ITERATIONS ]; then
        echo "failed to create kong db in postgres after $iter_num iterations"
        exit 1
    fi
done

# generate a random password using the automatic password generator (apg)
# debian package sourced from the Ubuntu 18.04 archive as a snap stage-package.
#
# -M ncl -- says the generator should use lowercase, uppercase, and numeric symbols
# -n 1   -- generate a single password
# -x 24  -- maximum password len
# -m 16  -- minimum password len
PGPASSWD=$("$SNAP/usr/lib/apg/apg" -a 0 -M ncl -n 1 -x 24 -m 16)
mkdir -p "$SNAP_DATA/config/postgres/"
echo "$PGPASSWD" > "$SNAP_DATA/config/postgres/kongpw"

# createuser doesn't support specification of a password, so use psql instead.
# Also as psql will use the database 'snap_daemon' by default, specify 'kong'
# via environment variable.
export PGDATABASE="kong"
iter_num=0
until "$SNAP/bin/drop-snap-daemon.sh" "$SNAP/bin/perl5lib-launch.sh" "$SNAP/usr/bin/psql" \
    "-c CREATE ROLE kong WITH NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN PASSWORD '$PGPASSWD'"; do
    sleep 1
    iter_num=$(( iter_num + 1 ))
    if [ $iter_num -gt $MAX_POSTGRES_INIT_ITERATIONS ]; then
        echo "failed to create kong user in postgres after $iter_num iterations"
        exit 1
    fi
done

# stop postgres again in case the security services should be turned off
snapctl stop "$SNAP_NAME.postgres"

# modify postgres authentication config to use 'md5' (password)
"$SNAP/bin/drop-snap-daemon.sh" sed -i -e "s@trust@md5@g" "$SNAP_DATA/postgresql/10/main/pg_hba.conf"

# finally, disable and turn off non-default services:
#
# - app-service-configurable (used for rules integration)
# - device-virtual
# - kuiper (replacement for support-rulesengine)
# - support-*
# - sys-mgmt-agent (see https://github.com/edgexfoundry/edgex-go/issues/2486)
#
for svc in support-notifications support-scheduler app-service-configurable device-virtual sys-mgmt-agent kuiper; do
    # set the service as off, so that the setting is persistent after a refresh
    # due to snapd bug: https://bugs.launchpad.net/snapd/+bug/1818306
    snapctl set $svc=off
    # also disable the service so it doesn't initially run - note that just 
    # setting the service as off above isn't quite what we want as the install
    # tasks go:
    # - install hook runs
    # - all non-disabled services are started
    # - configure hook runs (thus disabled services turned off)
    # as such, we don't want the services we turn off initially to be started
    # before the configure hook runs as it will be resource intensive for no
    # reason just to start a bunch of services and then immediately try to 
    # stop them afterwards
    snapctl stop --disable "$SNAP_NAME.$svc"
done
